﻿#pragma once

#include <functional>
#include <string>
#include <vector>

namespace kratos {
namespace console {

class Console;

/**
 * 控制台开关
 */
struct ConsoleSwitch {
  virtual ~ConsoleSwitch() {}
  /**
   * 设置开关的名字
   * \param display_name 开关的名字
   */
  virtual auto set_display_name(const std::string &display_name) -> void = 0;
  /**
   * 设置开关初始值
   * \param on_off 开关初始值
   */
  virtual auto set_on_off(bool on_off) -> void = 0;
  /**
   * 设置网页提示
   * \param tips 网页提示
   */
  virtual auto set_tips(const std::string &tips) -> void = 0;
  /**
   * @brief 获取用户数据
   * @return 用户数据
  */
  virtual auto get_user_data() -> std::uint64_t = 0;
};

/**
 * 开关数据刷新时调用
 * \param console 控制台实例
 * \param [OUT] cs 开关
 */
using ConsoleSwitchOnRefresh =
    std::function<void(Console &console, ConsoleSwitch &cs)>;
/**
 * 开关数据改变时调用
 * \param console 控制台实例
 * \param on_off true表示开，false表示关
 * \param [OUT] result 修改失败时的错误描述
 * \return true成功，false失败
 */
using ConsoleSwitchOnChange =
    std::function<bool(Console &console, bool on_off, std::string &result)>;

/**
 * 控制台开关plugin
 */
struct ConsoleSwitchPlugin {
  ConsoleSwitchOnRefresh refresh_method; ///< 刷新页面调用的方法
  ConsoleSwitchOnChange change_method;   ///< 开关改变调用的方法
  std::uint64_t user_data{0};            ///< 用户数据
};

/**
 * 控制台选项
 */
struct ConsoleSelection {
  virtual ~ConsoleSelection() {}
  /**
   * 设置开关的名字
   * \param display_name 开关的名字
   */
  virtual auto set_display_name(const std::string &display_name) -> void = 0;
  /**
   * 添加选项
   * \param selection 选项
   */
  virtual auto add_selection(const std::string &selection) -> void = 0;
  /**
   * 添加多个选项
   * \param selections 选项数组
   */
  virtual auto add_selection(const std::vector<std::string> &selections)
      -> void = 0;
  /**
   * 设置网页提示
   * \param tips 网页提示
   */
  virtual auto set_tips(const std::string &tips) -> void = 0;
  /**
   * @brief 获取用户数据
   * @return 用户数据
  */
  virtual auto get_user_data() -> std::uint64_t = 0;
};

/**
 * 选项数据刷新时调用
 * \param console 控制台实例
 * \param [OUT] cs 选项
 */
using ConsoleSelectionOnRefresh =
    std::function<void(Console &console, ConsoleSelection &cs)>;
/**
 * 选项数据改变时调用
 * \param console 控制台实例
 * \param name 列表内选项的名字
 * \param [OUT] result 修改失败时的错误描述
 * \return true成功，false失败
 */
using ConsoleSelectionOnSelect = std::function<bool(
    Console &console, const std::string &name, std::string &result)>;

/**
 * 控制台选项plugin
 */
struct ConsoleSelectionPlugin {
  ConsoleSelectionOnRefresh refresh_method; ///< 刷新页面调用的方法
  ConsoleSelectionOnSelect select_method;   ///< 选项改变调用的方法
  std::uint64_t user_data; ///< 用户数据
};

/**
 * 控制台接口
 */
class Console {
public:
  virtual ~Console() {}
  /**
   * 添加控制台开关plugin
   *
   * \param name 开关名字
   * \param switch_plugin plugin
   */
  virtual auto add_switch(const std::string &name,
                          ConsoleSwitchPlugin switch_plugin) -> void = 0;
  /**
   * 移除控制台开关plugin
   *
   * \param name 开关名字
   */
  virtual auto remove_switch(const std::string &name) -> void = 0;
  /**
   * 添加控制台选项plugin
   *
   * \param name 选项名字
   * \param selection_plugin plugin
   */
  virtual auto add_selection(const std::string &name,
                             ConsoleSelectionPlugin selection_plugin)
      -> void = 0;
  /**
   * 移除控制台选项plugin
   *
   * \param name 选项名字
   */
  virtual auto remove_selection(const std::string &name) -> void = 0;
  /**
   * @brief 获取当前的用户数据
   * @return 当前的用户数据
  */
  virtual auto get_current_user_data() -> std::uint64_t = 0;
};

} // namespace console
} // namespace kratos
